const jwt = require('jsonwebtoken')
const { promisify } = require('util')
const logger = require('./logger')

// JWT配置
const JWT_SECRET = process.env.JWT_SECRET || 'your_jwt_secret_key_here'
const JWT_EXPIRES_IN = process.env.JWT_EXPIRES_IN || '7d'
const JWT_REFRESH_EXPIRES_IN = process.env.JWT_REFRESH_EXPIRES_IN || '30d'

/**
 * 生成访问令牌
 * @param {Object} payload - 令牌载荷
 * @param {string} expiresIn - 过期时间
 * @returns {string} JWT令牌
 */
const generateAccessToken = (payload, expiresIn = JWT_EXPIRES_IN) => {
  try {
    return jwt.sign(payload, JWT_SECRET, {
      expiresIn,
      issuer: 'print-ad-system',
      audience: 'print-ad-users'
    })
  } catch (error) {
    logger.error('生成访问令牌失败:', error)
    throw new Error('令牌生成失败')
  }
}

/**
 * 生成刷新令牌
 * @param {Object} payload - 令牌载荷
 * @returns {string} JWT刷新令牌
 */
const generateRefreshToken = (payload) => {
  try {
    return jwt.sign(payload, JWT_SECRET, {
      expiresIn: JWT_REFRESH_EXPIRES_IN,
      issuer: 'print-ad-system',
      audience: 'print-ad-users'
    })
  } catch (error) {
    logger.error('生成刷新令牌失败:', error)
    throw new Error('刷新令牌生成失败')
  }
}

/**
 * 验证令牌
 * @param {string} token - JWT令牌
 * @returns {Promise<Object>} 解码后的载荷
 */
const verifyToken = async (token) => {
  try {
    const verify = promisify(jwt.verify)
    return await verify(token, JWT_SECRET, {
      issuer: 'print-ad-system',
      audience: 'print-ad-users'
    })
  } catch (error) {
    if (error.name === 'TokenExpiredError') {
      throw new Error('令牌已过期')
    } else if (error.name === 'JsonWebTokenError') {
      throw new Error('无效的令牌')
    } else if (error.name === 'NotBeforeError') {
      throw new Error('令牌尚未生效')
    } else {
      logger.error('令牌验证失败:', error)
      throw new Error('令牌验证失败')
    }
  }
}

/**
 * 解码令牌（不验证签名）
 * @param {string} token - JWT令牌
 * @returns {Object} 解码后的载荷
 */
const decodeToken = (token) => {
  try {
    return jwt.decode(token)
  } catch (error) {
    logger.error('令牌解码失败:', error)
    throw new Error('令牌解码失败')
  }
}

/**
 * 检查令牌是否即将过期
 * @param {string} token - JWT令牌
 * @param {number} threshold - 阈值（秒），默认1小时
 * @returns {boolean} 是否即将过期
 */
const isTokenExpiringSoon = (token, threshold = 3600) => {
  try {
    const decoded = decodeToken(token)
    if (!decoded || !decoded.exp) {
      return true
    }
    
    const now = Math.floor(Date.now() / 1000)
    const timeUntilExpiry = decoded.exp - now
    
    return timeUntilExpiry <= threshold
  } catch (error) {
    logger.error('检查令牌过期时间失败:', error)
    return true
  }
}

/**
 * 生成令牌对
 * @param {Object} payload - 用户信息载荷
 * @returns {Object} 包含访问令牌和刷新令牌的对象
 */
const generateTokenPair = (payload) => {
  const accessToken = generateAccessToken(payload)
  const refreshToken = generateRefreshToken({ userId: payload.userId })
  
  return {
    accessToken,
    refreshToken,
    expiresIn: JWT_EXPIRES_IN
  }
}

module.exports = {
  generateAccessToken,
  generateRefreshToken,
  verifyToken,
  decodeToken,
  isTokenExpiringSoon,
  generateTokenPair
}